/* -----------------------------------------------------------------------------
 * PROJECT    : lwf_handlers
 * FILE       : ArithmaticProcessHandler.java
 *
 * HISTORY:
 * Date          Author                        Description
 * ----------------------------------------------------------------------------- 
 * Jan 27, 2011  mycodetalks			       Created
 */
package net.lwf.handler.math.arithmatics;


import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;

import lwf.handler.entities.math.SumUtil;
import net.lwf.common.constant.ICommonConstant;
import net.lwf.entity.QuestionInfo;
import net.lwf.exception.ExceptionUtil;
import net.lwf.handler.constant.IHandlerConstant;
import net.lwf.handler.math.ArithGebraProcessHandler;
import net.lwf.number.util.NumberFormatter;
import net.lwf.pdf.util.FontUtil;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;


/**
 * Class description goes here
 */
public class ArithmaticProcessHandler extends ArithGebraProcessHandler {
	
	private static final String PDF_DATA_FILE = "arithmatic_pdf_data";
	
	//-----------------------------------------------------------------------------------
	// Constructors
	//-----------------------------------------------------------------------------------
	public ArithmaticProcessHandler(String grade, String operation) {
		super(grade, operation, PDF_DATA_FILE);
	}
	
	public ArithmaticProcessHandler(String grade, String operation, boolean needDecimals) {
		super(grade, operation, PDF_DATA_FILE, needDecimals);
	}
	
	//-----------------------------------------------------------------------------------
	// Abstract methods
	//-----------------------------------------------------------------------------------

	/**
	 * @return Returns the questiondesc.
	 */
	public String getQuestionDesc() {
		StringBuffer sbQ = new StringBuffer();
		if(this.getOperation().equals(IHandlerConstant.ADDITION)) {
			List<String> data = this.getAdddata();
			for(int i=0; i<data.size(); i++) {
				String qData = (String) data.get(i);
				sbQ.append(NumberFormatter.format(qData, getDecimaldigits()));
				if(i+1 < data.size()) {
					sbQ.append(" ");
					sbQ.append(this.getOperationsign());
					sbQ.append(" ");
				}
				else {
					sbQ.append(" = ");
				}
			}
		}
		else {
			sbQ.append(NumberFormatter.format(this.getData1(), getDecimaldigits()));
			sbQ.append(" ");
			sbQ.append(this.getOperationsign());
			sbQ.append(" ");	
			sbQ.append(NumberFormatter.format(this.getData2(), getDecimaldigits()));
			sbQ.append(" ");
			sbQ.append(" = ");
		}
		return sbQ.toString();
	}
	//-----------------------------------------------------------------------------------
	// Other public methods
	//-----------------------------------------------------------------------------------	
	
	@SuppressWarnings("unchecked")
	public QuestionInfo generateQuestion() {
		this.init();
		QuestionInfo question = generateSingle();
		List<Double> qdata = (List<Double>) question.getQuestionObject();
		
		//ArithmaticQuestion question = new ArithmaticQuestion();
		question.setOperation(getOperation());
		question.setDecimalDigits(getDecimaldigits());
		question.setAnswer(question.getAnswer());
		
		StringBuffer sbQ = new StringBuffer();
		int nCounter = 1;
		if(getOperation().equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			for(Double data: qdata) {
				String formattedData = NumberFormatter.format(data, getDecimaldigits(), true);
				sbQ.append(formattedData);
				if(nCounter < qdata.size()) {
					sbQ.append(" ");
					sbQ.append(SumUtil.getOperationImageHtml(getOperation()));
					sbQ.append(" ");
				}
				nCounter++;
			}
		}
		else {
			sbQ.append(NumberFormatter.format((Double) qdata.get(1), getDecimaldigits(), true));
			sbQ.append(" ");
			sbQ.append(SumUtil.getOperationImageHtml(getOperation()));
			sbQ.append(" ");
			sbQ.append(NumberFormatter.format((Double) qdata.get(0),getDecimaldigits(), true));
			sbQ.append(" ");
		}
		sbQ.append(" ");
		sbQ.append(ICommonConstant.EQUAL_TO);
		sbQ.append(" ");
		question.setQuestion(sbQ.toString() + ICommonConstant.QUESTION);
		
		StringBuffer sbQBlock = new StringBuffer("<table border=\"0\" align=\"center\" >");
		sbQBlock.append("<tr>");
		sbQBlock.append("<td class=\"datacenter\" >");
		sbQBlock.append(sbQ.toString());
		sbQBlock.append("</td>");
		sbQBlock.append("<td class=\"question\" >");
		sbQBlock.append(ICommonConstant.QUESTION);
		sbQBlock.append("</td>");
		sbQBlock.append("</tr>");
		sbQBlock.append("</table>");
		question.setHtmlQuestion(sbQBlock.toString());
		
		return question;
	}
	
	@SuppressWarnings("unchecked")
	public Element processCellData(QuestionInfo question) {
		List<Double> qdata = (List<Double>) question.getQuestionObject();
		
		PdfPTable table = new PdfPTable(2);
		//table.setExtendLastRow(true);
        //table.setWidthPercentage(20.0f);
		//table.setWidthPercentage(Float.parseFloat(pdfdata[2]));
        table.setSpacingBefore(20);
        Font displayfont = FontUtil.getDisplayFont(FontFactory.HELVETICA, 24);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("# " + question.getQuestionNumber(), FontUtil.getQuestionNumberFont()));
        cell.setBorder(0);
        cell.setColspan(2);
        table.addCell(cell);
        
        int nCounter = 1;
        int dataSize = qdata.size();
        
		for(int i=dataSize; i>0; i--) {
			if( i-1 != 0 ) {
				cell = new PdfPCell(new Phrase(""));
			}
			else {
				Image jpg = null;
				try {
					jpg = Image.getInstance(getBaseImagePath() + SumUtil.getOperationImagePath(getOperation()));
				} catch (BadElementException beex) {
					ExceptionUtil.logAndThrowException(getClass(), beex);
				} catch (MalformedURLException mfuex) {
					ExceptionUtil.logAndThrowException(getClass(), mfuex);
				} catch (IOException ioex) {
					ExceptionUtil.logAndThrowException(getClass(), ioex);
				}
				cell = new PdfPCell(jpg);
			}
	        cell.setBorder(0);
	        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
	        table.addCell(cell);
	        
			String formattedData = NumberFormatter.format(qdata.get(i-1), getDecimaldigits(), true);
			cell = new PdfPCell(new Phrase(formattedData, displayfont));
			cell.setNoWrap(true);
			cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
			cell.setBorder(0);
			table.addCell(cell);
			nCounter++;
		}
		if(getOperation().equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			cell = new PdfPCell(new Phrase(IHandlerConstant.REMAINDER, FontUtil.getDisplayFont()));
		}
		else {
			cell = new PdfPCell(new Phrase(" "));
		}
        
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setColspan(2);
        cell.setBorder(0);
        cell.setBorderWidthTop(1.25f);
        cell.setBorderWidthBottom(1.25f);
        cell.setFixedHeight(30);
        table.addCell(cell);
        table.completeRow();

        
		return table;
	}



	/**
	 * Determines whether to show the remainder text box on the UI or not.
	 * This is called from the action class once the handler is initialized.
	 * 
	 * @return
	 */
	public boolean showRemainderTextBox() {
		if(getOperation().equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			if(getDecimaldigits() == 0) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @see net.lwf.handler.ProcessHandler#getPdfInstructionalText()
	 */
	public String getPdfInstructionalText() {
		String text = "Solve the following ";
		if(getOperation().equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			text += IHandlerConstant.ADDITION;
		}
		else if(getOperation().equalsIgnoreCase(IHandlerConstant.SUBTRACTION)) {
			text += IHandlerConstant.SUBTRACTION;
		}
		else if(getOperation().equalsIgnoreCase(IHandlerConstant.MULTIPLICATION)) {
			text += IHandlerConstant.MULTIPLICATION;
		}
		else  {
			text += IHandlerConstant.DIVISION;
		}
		return text + " problems.";
	}

	//-----------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------


} // ArithmaticProcessHandler
/*
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

import lwf.handler.IProcessHandler;
import lwf.handler.ProcessHandler;
import lwf.handler.entities.math.Sum;
import lwf.handler.entities.math.SumUtil;
import lwf.handler.helper.DisplayFormatter;
import lwf.handler.util.SumGenerator;
import net.lwf.common.constant.ICommonConstant;
import net.lwf.jaxb.entity.AttemptedQuestion;
import net.lwf.jaxb.entity.QuestionInfo;
import net.lwf.exception.ExceptionUtil;
import net.lwf.handler.constant.IHandlerConstant;
import net.lwf.jaxb.entity.BaseData;
import net.lwf.jaxb.service.XMLDataService;
import net.lwf.number.util.NumberFormatter;
import net.lwf.pdf.util.FontUtil;
import net.lwf.string.util.StringManipulator;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;


*//**
 * Class description goes here
 *//*
public class ArithmaticProcessHandler extends ProcessHandler implements IProcessHandler {

	private String operation;
	private int digits;
	private int datarows;
	private int decimaldigits;
	private String[] pdfdata;
	
	//-----------------------------------------------------------------------------------
	// Constructors
	//-----------------------------------------------------------------------------------
	public ArithmaticProcessHandler(String grade, String operation) {
		super(grade);
		this.operation = operation;
	}
	
	//-----------------------------------------------------------------------------------
	// Abstract methods
	//-----------------------------------------------------------------------------------
	@Override
	public List<QuestionInfo> generateMultiple() {
		this.initPdfInfo();
		List<QuestionInfo> questions = new ArrayList<QuestionInfo>();
		int nQuestions = getRows() * getColumns();
		for(int i=0; i<nQuestions; i++) {
			QuestionInfo question = generateSingle();
			question.setQuestionNumber(i+1);
			questions.add(question);
		}
		return questions;
	}

	@Override
	public QuestionInfo generateSingle() {
		QuestionInfo qinfo = new QuestionInfo();
		Sum sum = this.generateSum();
		qinfo.setQuestionObject(sum.getData());
		//sum.print();
		qinfo.setAnswer(this.getFormattedAnswer(sum.getAnswer()));
		return qinfo;
	}
	
	@Override
	public int getColumns() {
		return Integer.parseInt(pdfdata[1]);
	}

	@Override
	public void getContent(Document document) throws DocumentException {
	}

	@Override
	public int getRows() {
		return Integer.parseInt(pdfdata[0]);
	}

	@Override
	public boolean isPortrait() {
		return true;
	}
	
	//-----------------------------------------------------------------------------------
	// Interface implemented methods
	//-----------------------------------------------------------------------------------
	public DisplayFormatter getDisplayFormatter() {
		return null;
	}

	*//**
	 * @return Returns the questiondesc.
	 *//*
	@SuppressWarnings("unchecked")
	public String getQuestionDesc() {
		StringBuffer sbQ = new StringBuffer();
		if(this.getOperation().equals(IHandlerConstant.ADDITION)) {
			List data = this.getAdddata();
			for(int i=0; i<data.size(); i++) {
				String qData = (String) data.get(i);
				sbQ.append(NumberFormatter.format(qData, this.decimaldigits));
				if(i+1 < data.size()) {
					sbQ.append(" ");
					sbQ.append(this.getOperationsign());
					sbQ.append(" ");
				}
				else {
					sbQ.append(" = ");
				}
			}
		}
		else {
			sbQ.append(NumberFormatter.format(this.getData1(), this.decimaldigits));
			sbQ.append(" ");
			sbQ.append(this.getOperationsign());
			sbQ.append(" ");	
			sbQ.append(NumberFormatter.format(this.getData2(), this.decimaldigits));
			sbQ.append(" ");
			sbQ.append(" = ");
		}
		return sbQ.toString();
	}
	//-----------------------------------------------------------------------------------
	// Other public methods
	//-----------------------------------------------------------------------------------	
	
	@SuppressWarnings("unchecked")
	public ArithmaticQuestion generateQuestion() {
		this.init();
		QuestionInfo qinfo = generateSingle();
		List<Double> qdata = (List<Double>) qinfo.getQuestionObject();
		
		ArithmaticQuestion question = new ArithmaticQuestion();
		question.setOperation(this.operation);
		question.setDecimalDigits(this.decimaldigits);
		question.setAnswer(qinfo.getAnswer());
		
		StringBuffer sbQ = new StringBuffer();
		int nCounter = 1;
		if(this.operation.equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			for(Double data: qdata) {
				String formattedData = NumberFormatter.format(data, this.decimaldigits, true);
				sbQ.append(formattedData);
				if(nCounter < qdata.size()) {
					sbQ.append(" ");
					sbQ.append(SumUtil.getOperationImageSign(this.operation));
					sbQ.append(" ");
				}
				nCounter++;
			}
		}
		else {
			sbQ.append(NumberFormatter.format((Double) qdata.get(1), this.decimaldigits, true));
			sbQ.append(" ");
			sbQ.append(SumUtil.getOperationImageSign(this.operation));
			sbQ.append(" ");
			sbQ.append(NumberFormatter.format((Double) qdata.get(0),this.decimaldigits, true));
			sbQ.append(" ");
		}
		question.setQuestion(sbQ.toString() + " = ?");
		
		StringBuffer sbQBlock = new StringBuffer("<table border=\"0\" >");
		sbQBlock.append("<tr>");
		sbQBlock.append("<td class=\"data\" >");
		sbQBlock.append(sbQ.toString());
		sbQBlock.append("</td>");
		sbQBlock.append("<td class=\"question\" >");
		sbQBlock.append("?");
		sbQBlock.append("</td>");
		sbQBlock.append("</tr>");
		sbQBlock.append("</table>");
		question.setHtmlQuestion(sbQBlock.toString());
		
		return question;
	}
	
	@SuppressWarnings("unchecked")
	public Element processCellData(QuestionInfo question) {
		List<Double> qdata = (List<Double>) question.getQuestionObject();
		
		PdfPTable table = new PdfPTable(2);
		//table.setExtendLastRow(true);
        //table.setWidthPercentage(20.0f);
		//table.setWidthPercentage(Float.parseFloat(pdfdata[2]));
        table.setSpacingBefore(20);
        Font displayfont = FontUtil.getDisplayFont(FontFactory.HELVETICA, 24);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("# " + question.getQuestionNumber(), FontUtil.getQuestionNumberFont()));
        cell.setBorder(0);
        cell.setColspan(2);
        table.addCell(cell);
        
        int nCounter = 1;
        int dataSize = qdata.size();
        
		for(int i=dataSize; i>0; i--) {
			if( i-1 != 0 ) {
				cell = new PdfPCell(new Phrase(""));
			}
			else {
				Image jpg = null;
				try {
					jpg = Image.getInstance(getBaseImagePath() + SumUtil.getImagePath(this.operation));
				} catch (BadElementException beex) {
					ExceptionUtil.logAndThrowException(getClass(), beex);
				} catch (MalformedURLException mfuex) {
					ExceptionUtil.logAndThrowException(getClass(), mfuex);
				} catch (IOException ioex) {
					ExceptionUtil.logAndThrowException(getClass(), ioex);
				}
				cell = new PdfPCell(jpg);
			}
	        cell.setBorder(0);
	        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
	        table.addCell(cell);
	        
			String formattedData = NumberFormatter.format(qdata.get(i-1), this.decimaldigits, true);
			cell = new PdfPCell(new Phrase(formattedData, displayfont));
			cell.setNoWrap(true);
			cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
			cell.setBorder(0);
			table.addCell(cell);
			nCounter++;
		}
		if(this.operation.equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			cell = new PdfPCell(new Phrase(IHandlerConstant.REMAINDER, FontUtil.getDisplayFont()));
		}
		else {
			cell = new PdfPCell(new Phrase(" "));
		}
        
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setColspan(2);
        cell.setBorder(0);
        cell.setBorderWidthTop(1.25f);
        cell.setBorderWidthBottom(1.25f);
        cell.setFixedHeight(30);
        table.addCell(cell);
        table.completeRow();

        
		return table;
	}

	public boolean matchAnswer(String useranswer, AttemptedQuestion attemptedQuestion) {
		//remove "," if any
		if(useranswer != null && useranswer.trim().length() != 0) {
			useranswer = StringManipulator.replace(useranswer, ICommonConstant.COMMA, "");
		}
		ArithmaticQuestion aq = (ArithmaticQuestion) attemptedQuestion;
		boolean returnvalue = false;
		String formattedAnswer;
		if(this.operation.equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			StringTokenizer stk_ua = new StringTokenizer(useranswer.trim(), ICommonConstant.PIPE);
			if(aq.getDecimalDigits() == 0) {
				String ui_quotient = NumberFormatter.format(stk_ua.nextToken(), 0);
				String ui_remainder = NumberFormatter.format(stk_ua.nextToken(), 0); 
				formattedAnswer = ui_quotient + IHandlerConstant.REMAINDER + ui_remainder;
			}
			else {
				//Consider only the quotient value
				String ui_quotient = NumberFormatter.format(useranswer, aq.getDecimalDigits());
				formattedAnswer = ui_quotient + IHandlerConstant.REMAINDER + "0";
			}
		}
		else {
			formattedAnswer = NumberFormatter.format(useranswer.trim(), aq.getDecimalDigits());
		}
		
		if(attemptedQuestion.getAnswer().equalsIgnoreCase(formattedAnswer)) {
			return true;
		}

		return returnvalue;
	}

	*//**
	 * Determines whether to show the remainder text box on the UI or not.
	 * This is called from the action class once the handler is initialized.
	 * 
	 * @return
	 *//*
	public boolean showRemainderTextBox() {
		if(this.operation.equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			if(this.decimaldigits == 0) {
				return true;
			}
		}
		return false;
	}
	
	*//**
	 * @see net.lwf.handler.ProcessHandler#getInstructionalText()
	 *//*
	public String getInstructionalText() {
		String text = "Solve the following ";
		if(this.operation.equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			text += IHandlerConstant.ADDITION;
		}
		else if(this.operation.equalsIgnoreCase(IHandlerConstant.SUBTRACTION)) {
			text += IHandlerConstant.SUBTRACTION;
		}
		else if(this.operation.equalsIgnoreCase(IHandlerConstant.MULTIPLICATION)) {
			text += IHandlerConstant.MULTIPLICATION;
		}
		else  {
			text += IHandlerConstant.DIVISION;
		}
		return text + " problems.";
	}

	//-----------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------
	public void init() {
	//private void init() {	//To go in a common super class
		XMLDataService service = new XMLDataService();
		BaseData data = service.getArithmaticData(Integer.parseInt(getGrade()), operation);
		//Read the value by JAXB code - input = grade; output = digits, decimal points
		this.digits = data.getDigits();
		this.datarows = data.getDatarows();
		this.decimaldigits = data.getDecimals();
	}
	
	private void initPdfInfo() {
		this.init();
		this.pdfdata = this.getPdfData(operation + "-" + this.digits + "-" + this.decimaldigits + "-" + this.datarows);
	}
	private String[] getPdfData(String key) {
		String[] pdfdata = new String[2];
		ResourceBundle bundle = ResourceBundle.getBundle("arithmatic_pdf_data");
		String data = bundle.getString(key);
		StringTokenizer stk = new StringTokenizer(data, ICommonConstant.PIPE);
		pdfdata[0] = stk.nextToken();
		pdfdata[1] = stk.nextToken();
		return pdfdata;
	}
	
	//private String getFormattedAnswer(Object answerobj) {
	public String getFormattedAnswer(Object answerobj) { //To go in a common super class
		String formattedAnswer = "";
		if(this.operation.equalsIgnoreCase(IHandlerConstant.DIVISION)) {
			String answerdata = String.valueOf(answerobj);
			String quotient = String.valueOf(answerobj);
			String remainder = "0";
			if(answerdata.indexOf(ICommonConstant.PIPE) != -1) {
				StringTokenizer stk = new StringTokenizer(answerdata, ICommonConstant.PIPE);
				quotient = stk.nextToken();
				remainder = stk.nextToken();
			}

			formattedAnswer = NumberFormatter.format(String.valueOf(quotient), this.decimaldigits) + 
			                  IHandlerConstant.REMAINDER +
			                  NumberFormatter.format(String.valueOf(remainder), this.decimaldigits);
		}
		else {
			formattedAnswer = NumberFormatter.format(String.valueOf(answerobj), this.decimaldigits);
		}
		return formattedAnswer;
	}
	
	//private Sum generateSum() {
	public Sum generateSum() { //To go in a common super class
		Sum sum = null;
		if(this.operation.equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			sum = SumGenerator.generateAdd(this.digits, this.datarows, this.decimaldigits);
		}
		else if(this.operation.equalsIgnoreCase(IHandlerConstant.SUBTRACTION)) {
			sum = SumGenerator.generateSubtract(this.digits, this.decimaldigits);
		}
		else if(this.operation.equalsIgnoreCase(IHandlerConstant.MULTIPLICATION)) {
			sum = SumGenerator.generateMultiply(this.digits, this.decimaldigits);
		}
		else  {
			sum = SumGenerator.generateDevide(this.digits, this.decimaldigits);
		}
		return sum;
	}

} // ArithmaticProcessHandler
*/


